package consensus

import (
	"osiris/dto"
	"sync"

	"github.com/libp2p/go-libp2p/core/crypto"
	peer "github.com/libp2p/go-libp2p/core/peer"
)

const (
	bufSize = 5
)

var (
	blockHeaderBuf []dto.BlockHeader
	bufMutex       *sync.RWMutex
)

// ConsensusProtocol 共识机制
type ConsensusProtocol interface {

	// OnCreateBlock 创造区块的操作
	//  @param chainID
	//  @param blockJsonChan 订阅区块创造完成的通道
	//  @return error
	OnCreateBlock(chainID int, blockJsonChan chan string) error

	// OnReceiveBlock 收到区块后的操作
	//  @param blockDto
	//  @param pubKey 记账节点的公钥
	//  @return error
	OnReceiveBlock(blockDto dto.BlockDto, pubKey crypto.PubKey) error

	// onBlockVerified 区块被确认后的操作
	//  @param blockDto
	onBlockVerified(blockDto dto.BlockDto)
}

func init() {
	blockHeaderBuf = make([]dto.BlockHeader, bufSize)
	bufMutex = new(sync.RWMutex)
}

func AddRecentHeader(header dto.BlockHeader) {
	bufMutex.Lock()
	defer bufMutex.Unlock()

	if len(blockHeaderBuf) < bufSize {
		blockHeaderBuf = append(blockHeaderBuf, header)
		return
	}

	blockHeaderBuf = blockHeaderBuf[1:]
	blockHeaderBuf = append(blockHeaderBuf, header)
}

func IsHeaderInBuf(header dto.BlockHeader) bool {
	bufMutex.RLock()
	defer bufMutex.RUnlock()

	for _, tempHeader := range blockHeaderBuf {
		if tempHeader.HeaderHash == header.HeaderHash && tempHeader.Timestamp == header.Timestamp {
			return true
		}
	}

	return false
}

func OnCreateBlock(chainID int, peerID peer.ID, blockJsonChan chan string) error {
	return POS{
		ChainID: chainID,
		PeerID:  peerID,
	}.OnCreateBlock(blockJsonChan)
}

func OnReceiveBlock(chainID int, peerID peer.ID, blockDto dto.BlockDto, pubKey crypto.PubKey) error {
	return POS{
		ChainID: chainID,
		PeerID:  peerID,
	}.OnReceiveBlock(blockDto, pubKey)
}
